/*
自动申请字符设备号

安装次模块，将
    在/proc/devices文件里生成设备(auto_chrdev)及其主设备号

*/


#include "linux/init.h"
#include "linux/module.h"
#include "linux/fs.h"

static uint32_t auto_chrdev_id_major = 0;
static const char *auto_chrdev_name = "auto_chrdev";
static struct file_operations auto_chrdev_fops;
static uint8_t registered = 0;

static int __init auto_chrdev_init(void)
{
    int ret = -1;

    printk("file=%s,fun=%s,line=%d\n", __FILE__, __FUNCTION__, __LINE__);

    /*
    若major=0，则自动注册，成功并返回主设备号，失败返回负数
    若major>0，则尝试基于该主设备号进行注册，失败返回负数
    */
    ret = register_chrdev(0, auto_chrdev_name, &auto_chrdev_fops);
    if (ret < 0)
    {
        printk("register_chrdev error\n");
        return -1;
    }
    auto_chrdev_id_major = ret;
    printk("auto_chrdev_id_major=%u,MAJOR=%u,MINOR=%u\n", auto_chrdev_id_major, MAJOR(auto_chrdev_id_major), MINOR(auto_chrdev_id_major));

    registered = 1;

    return 0;
}

static void __exit auto_chrdev_exit(void)
{
    printk("file=%s,fun=%s,line=%d\n", __FILE__, __FUNCTION__, __LINE__);

    if (registered)
    {
        unregister_chrdev(auto_chrdev_id_major, auto_chrdev_name);
    }
}

module_init(auto_chrdev_init);
module_exit(auto_chrdev_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("lxz");
